package cn.hiapi.core.utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;

public class ImageUtils {


    private static final String FONT_PATH = "https://all-style.oss-cn-hangzhou.aliyuncs.com/font/heiti.TTF";

    /**
     * 图片剪切
     *
     * @param bufferedImage
     * @param startX
     * @param startY
     * @param endX
     * @param endY
     * @return
     */
    public static BufferedImage cropImage(BufferedImage bufferedImage, int startX, int startY, int endX, int endY) {
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        if (startX == -1) {
            startX = 0;
        }
        if (startY == -1) {
            startY = 0;
        }
        if (endX == -1) {
            endX = width - 1;
        }
        if (endY == -1) {
            endY = height - 1;
        }
        BufferedImage result = new BufferedImage(endX - startX, endY - startY, 4);
        for (int x = startX; x < endX; ++x) {
            for (int y = startY; y < endY; ++y) {
                int rgb = bufferedImage.getRGB(x, y);
                result.setRGB(x - startX, y - startY, rgb);
            }
        }
        return result;
    }

    public static BufferedImage roundImage(BufferedImage image, int round) {

        int w = image.getWidth();
        int h = image.getHeight();
        BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = null;
        try {
            g2 = output.createGraphics();
            g2.setComposite(AlphaComposite.Src);
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            g2.setColor(Color.WHITE);
            g2.fill(new RoundRectangle2D.Float(0, 0, w, h, round, round));

            g2.setComposite(AlphaComposite.SrcAtop);
            g2.drawImage(image, 0, 0, null);
        } finally {
            if (g2 != null) g2.dispose();
        }


        return output;
    }

    public static BufferedImage roundImage(String url, int round) throws IOException {
        return roundImage(ImageIO.read(new URL(url)), round);
    }


    /**
     * 生成图形验证码
     *
     * @param code
     * @param width
     * @param height
     * @return
     */
    public static byte[] generateImageVerify(String code, int width, int height) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = null;
        Graphics graphics = null;
        try {
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            graphics = image.getGraphics();
            graphics.setColor(new Color(255, 255, 255));
            graphics.fillRect(0, 0, width, height);
            char[] chars = code.toCharArray();
            for (int i = 0; i < chars.length; i++) {
                char c = chars[i];
                graphics.setColor(new Color(0, 0, 0));
                graphics.setFont(new Font("Times New Roman", Font.BOLD, 25));
                graphics.drawString(c + "", 15 * i + 10, 20);
            }
            for (int i = 0; i < 5; i++) {
                int x1 = (int) (Math.random() * width);
                int y1 = (int) (Math.random() * height);
                int x2 = (int) (Math.random() * width);
                int y2 = (int) (Math.random() * height);
                graphics.setColor(new Color(0, 0, 0));
                graphics.drawLine(x1, y1, x2, y2);
            }
            byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write(image, "png", byteArrayOutputStream);
            return byteArrayOutputStream.toByteArray();
        } finally {
            if (graphics != null) graphics.dispose();
            try {
                if (byteArrayOutputStream == null) byteArrayOutputStream.close();
            } catch (Exception ex) {
            }
        }
    }


    public static void drawImage(Graphics graphics, BufferedImage image, int width, int height, int x, int y) {

        Graphics2D graphics2D = null;
        try {
            graphics2D = image.createGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            graphics.drawImage(image, x, y, width, height, null);
        } finally {
            if (graphics2D != null) graphics2D.dispose();
        }
    }

    public static void drawImage(Graphics graphics, String url, int width, int height, int x, int y) throws IOException {
        URL u = new URL(url);
        drawImage(graphics, ImageIO.read(u), width, height, x, y);
    }

    public static void drawString(Graphics graphics, String text, Color color, Font font, int x, int y) {
        graphics.setColor(color);
        graphics.setFont(font);
        graphics.drawString(text, x, (y + font.getSize()));
    }

    public static void drawString(Graphics graphics, String text, Color color, int fontStyle, float fontSize, int x, int y) throws IOException {
        Font font = loadFont()
                .deriveFont(fontStyle, fontSize);
        drawString(graphics, text, color, font, x, y);
    }

    public static void drawString(Graphics graphics, String text, Color color, float fontSize, int x, int y) throws IOException {
        Font font = loadFont()
                .deriveFont(fontSize);
        drawString(graphics, text, color, font, x, y);
    }

    public static void drawString(Graphics graphics, String text, String colorHex, int fontStyle, float fontSize, int x, int y) throws IOException {
        Font font = loadFont()
                .deriveFont(fontStyle, fontSize);
        drawString(graphics, text, Color.decode(colorHex), font, x, y);
    }


    public static Font loadFont() throws IOException {
        String path = System.getProperty("user.dir") + "/fontfile";
        if (Files.notExists(Paths.get(path))) {
            boolean download = HttpService.getInstance().download(FONT_PATH, path);
            if (!download) throw new RuntimeException("字体下载失败");
        }
        try {
            return Font.createFont(0, new File(path));
        } catch (FontFormatException e) {
            throw new RuntimeException(e);
        }
    }


    public static BufferedImage createImage(Color bg, int width, int height) {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = null;
        try {
            graphics = image.createGraphics();
            image = graphics.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
            graphics = image.createGraphics();
            graphics.setColor(bg);
            graphics.fillRect(0, 0, width, height);
            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 0.3f是透明系数 ，透明系数取值范围是 0 ~ 1.0
            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f));
        } finally {
            if (graphics != null) graphics.dispose();
        }

        return image;
    }
}
